home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / comm / xpr.2 < prev    next >
Internet Message Format  |  1989-08-21  |  69KB

  1. Path: xanth!ames!sun-barr!newstop!sun!swap!page
  2. From: page%swap@Sun.COM (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i171:  xpr - external file transfer protocol library, Part02/02
  5. Message-ID: <122692@sun.Eng.Sun.COM>
  6. Date: 21 Aug 89 06:09:29 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1859
  9. Approved: page@sun.com
  10.  
  11. Submitted-by: papa@pollux.usc.edu (Marco Papa)
  12. Posting-number: Volume 89, Issue 171
  13. Archive-name: comm/xpr.2
  14.  
  15. [this archive consists of only the document.  ..bob]
  16.  
  17. # This is a shell archive.
  18. # Remove anything above and including the cut line.
  19. # Then run the rest of the file through 'sh'.
  20. # Unpacked files will be owned by you and have default permissions.
  21. #----cut here-----cut here-----cut here-----cut here----#
  22. #!/bin/sh
  23. # shar: SHell ARchive
  24. # Run the following text through 'sh' to create:
  25. #    xprotocol.doc
  26. # This is archive 2 of a 2-part kit.
  27. # This archive created: Sun Aug 20 23:01:48 1989
  28. echo "extracting xprotocol.doc"
  29. sed 's/^X//' << \SHAR_EOF > xprotocol.doc
  30. X+----------------------------------------------------------------------+
  31. X|                                                                      |
  32. X|                  D I S C L A I M E R   N O T I C E                   |
  33. X|                                                                      |
  34. X|  This document and/or  portions of the material and  data furnished  |
  35. X|  herewith,  was developed under sponsorship of the U.S. Government.  |
  36. X|  Neither the U.S.  nor  the U.S.D.O.E.,  nor  the  Leland  Stanford  |
  37. X|  Junior University, nor their employees,  nor their respective con-  |
  38. X|  tractors, subcontractors, or their employees, makes  any warranty,  |
  39. X|  express or implied, or assumes any liability or responsibility for  |
  40. X|  accuracy,  completeness or  usefulness of any information, appara-  |
  41. X|  tus, product or process disclosed, or represents that its use will  |
  42. X|  not infringe privately-owned rights.  Mention of any product,  its  |
  43. X|  manufacturer, or suppliers shall not, nor is it intended to, imply  |
  44. X|  approval, disapproval, or fitness for any particular use. The U.S.  |
  45. X|  and  the University at all times  retain the right to use and dis-  |
  46. X|  seminate same for any purpose whatsoever.                           |
  47. X|                                                                      |
  48. X+----------------------------------------------------------------------+
  49. X
  50. X
  51. X
  52. X        XPR: External File Transfer Protocols as Amiga Libraries.
  53. X        =========================================================
  54. X
  55. X                       Version - 10 July 1989
  56. X
  57. X                       (C) Copyright 1989 by
  58. X
  59. X                         W.G.J. Langeveld
  60. X
  61. X                 Stanford Linear Accelerator Center
  62. X
  63. X
  64. X                              ABSTRACT
  65. X                              ========
  66. X
  67. X                This document describes a standard method
  68. X                of using Amiga shared libraries  for  the
  69. X                implementation of  external file transfer
  70. X                protocols, as (partially) implemented  in
  71. X                the Amiga terminal emulator VLT.
  72. X
  73. X
  74. X1. Introduction.
  75. X================
  76. X
  77. X        One of the most frequently asked questions of the author of a
  78. Xcommunications program is "Why don't you implement this wonderful file transfer
  79. Xprotocol in addition to the 25 you already have?". Clearly, implementing more
  80. XFTP's leads to larger code size and to increased product development time and
  81. Xcustomer support requirements, unless there is a way to have the additional
  82. Xprotocols available as separate entities. One obvious way is to put the
  83. Xadditional FTP's in overlays, but that only mitigates the code size problem and
  84. Xdoes not allow protocols to be used with communications programs of different
  85. Xvendors. Better is to open the serial device as a shared port and to have a
  86. Xcompletely separate program access it at the same time. However, this method has
  87. Xthe disadvantage that shared use of a single serial port can lead to
  88. Xunpredictable results unless there is a well-established priority system
  89. Xenforcing which program is allowed to write to the device at which time. The
  90. Xadvantage is that the FTP can now be developed separately and even by someone
  91. Xother than the author of the communications program. There are variations
  92. Xinvolving inter-process communication to add access control to the latter
  93. Xsystem, but I will not go into further detail.
  94. X        The system described here is based on Amiga shared libraries. The
  95. Xlibrary implements a small number of primary functions, such as "Send File(s)"
  96. Xand "Receive File(s)". These functions are called with a single argument, a
  97. Xpointer to an XPR_IO structure. This structure contains a number of things, the
  98. Xmore obvious one being a pointer to a null terminated string indicating which
  99. Xfiles are to be sent or received and addresses of "call-back" functions inside
  100. Xthe code of the communications program to access the serial device, which is
  101. Xopened typically in exclusive access. The scheme described here opens the
  102. Xpossibility for the Amiga community to write a multitude of file transfer
  103. Xprotocols, all rather small in size because they don't contain any overhead,
  104. Xthat work with any communications program following the rules outlined in this
  105. Xdocument.
  106. X        Possible problems with shared libraries are that they should be
  107. Xreentrant and that they should, if possible, not open dos.library [1]. On the
  108. Xother hand, these problems can easily be turned into advantages: for one,
  109. Xreentrancy is not hard to accomplish and in addition when there are multiple
  110. Xserial ports in use all of them can use the FTP with a single copy of the code.
  111. XNot having to open dos.library can be accomplished by having call-back functions
  112. Xthat provide all the DOS access needed in the original communications program.
  113. XTypically these DOS functions are already linked into the original code anyway,
  114. Xand call-backs have to be provided for serial port access in any case.
  115. X        For the sake of reentrancy across calls to the external protocol library
  116. X(XPR), a field for storing a pointer to a data area is added for use by the XPR
  117. Xinternally.
  118. X
  119. X        Section 2 explains the library structure itself. Section 3 covers the
  120. XXPR_IO structure and defines all the call-back functions. Section 4 describes an
  121. Xexample library for a simple ASCII transfer without bells or whistles and will
  122. Xshow how to code the library part of the call-backs. Section 5 shows how to set
  123. Xup the interface on the communications program side.
  124. X
  125. X        Note: the examples are all for Manx C and assembler but should be easily
  126. Xmodifyable for Lattice or any other language. Not all source files are given in
  127. Xthis document. This archive, however, contains the example library plus all
  128. Xfiles needed to link it and interface to it, for Manx. Specifically, the
  129. Xroutines that interface to XPR from VLT are in the "comm-program" subdirectory,
  130. Xand the sources to the library are in the "library" subdirectory.
  131. X
  132. X        I would like to thank Marco Papa of Felsina Software for his help in
  133. Xworking out some of the details of the XPR standard.
  134. X
  135. X        Neither this document, nor the XPR standard, nor the other files in this
  136. Xarchive are in the public domain, but they may be freely distributed and used
  137. Xfor any purpose bearing in mind the stipulations given in the disclaimer above,
  138. Xand with the proviso that in case of further distribution all files of this
  139. Xarchive must remain together and unchanged.
  140. X
  141. X
  142. XReference:
  143. X[1] Jim Mackraz says that opening dos.library inside a library is not a good
  144. X    idea.
  145. X
  146. X
  147. X2. XPR libraries.
  148. X=================
  149. X
  150. X        Each external FTP is implemented as a separate library which lives in
  151. Xthe libs: directory. It is mandatory that the names of XPR libraries start with
  152. Xthe three letters "xpr" so that they are easily identified. The template for the
  153. Xname is xpr<protocol-name>.library, where <protocol-name> is a descriptive name
  154. Xof the protocol that is implemented. Obvious examples would be xprkermit.library
  155. Xand xprxmodem.library, but xprmykermit.library would be fine for a
  156. Xuser-customized kermit implementation. When thinking of a name, the  implementer
  157. Xof an XPR library should keep in mind that communication programs will likely
  158. Xuse the <protocol-name> part in their XPR requester.
  159. X        Each XPR library in turn has four public functions. The functions are:
  160. X
  161. X        XProtocolCleanup()
  162. X        XprotocolSetup()
  163. X        XprotocolSend()    and
  164. X        XprotocolReceive()
  165. X
  166. Xin addition to the usual open, close expunge and reserved vectors. The library
  167. Xskeleton is given in Appendix A.
  168. X        Typically, a session with a terminal emulator using external protocols
  169. Xwould consist of
  170. X
  171. X        1. Selecting an external protocol (Using e.g. a file requester
  172. X           showing only those files in libs: starting with "xpr").
  173. X        2. Retrieving the library base XProtocolBase of the selected protocol
  174. X           using OpenLibrary().
  175. X        3. (Allocating and) initializing an XPR_IO structure.
  176. X        4. Optionally calling XProtocolSetup() with the initialized structure.
  177. X        5. Optionally Calling XProtocolSend() and/or XprotocolReceive() once or
  178. X           multiple times to transfer files.
  179. X        6. Optionally calling XProtocolSetup() to change parameters or to send
  180. X           special commands. Perhaps repeat 5.
  181. X        7. Calling XprotocolCleanup() to deallocate any resources allocated by
  182. X           XProtocolSetup(). (Deallocate the XPR_IO structure if needed).
  183. X        8. Closing the library using CloseLibrary().
  184. X        9. Repeat the process, or
  185. X       10. Exit.
  186. X
  187. X        All four XPR functions take a single argument, a pointer to an XPR_IO
  188. Xstructure, properly initialized as described in section 5. After
  189. XXProtocolSetup() has been called, the same XPR_IO structure should be used for
  190. Xcalls to any of the other functions. Only the xpr_filename field is allowed to
  191. Xbe changed between  calls. In particular, the xpr_data field is for internal use
  192. Xby the XPR library only! It should be initialized to NULL before calling
  193. XXProtocolSetup() and should not be changed by the communications program.
  194. XXProtocolSetup() should only be called at the request of the user.
  195. XXProtocolCleanup() should always be called before the library is closed.
  196. X        In the form of a sample program, the rules above look like this:
  197. X
  198. X/** MyWonderFullCommProgram.c
  199. X*
  200. X*   Just an example. An actual implementation would likely look different.
  201. X*
  202. X**/
  203. X#include <stdio.h>
  204. X#include <functions.h>
  205. X#include "xproto.h"
  206. X
  207. Xstruct Library *XProtocolBase = NULL;
  208. X
  209. X#define SEND 1
  210. X#define RECEIVE 2
  211. X#define INITIALIZE 3
  212. X
  213. Xmain()
  214. X{
  215. X   struct XPR_IO io;
  216. X   int user_said, Waiting_for_user_input();
  217. X
  218. X   XProtocolBase = OpenLibrary("xprascii.library", 0L);
  219. X   if (XProtocolBase == NULL) {
  220. X      printf("protocol not found\n");
  221. X      exit(10);
  222. X   }
  223. X
  224. X/*
  225. X*   Initialize structure (see later).
  226. X*/
  227. X   xpr_setup(io);
  228. X/*
  229. X*   Retrieve the initalization string
  230. X*/
  231. X   Get_init_string_from_user_or_wherever(buffer);
  232. X   io->xpr_filename = buffer;
  233. X   XProtocolSetup(io);
  234. X
  235. X   while (user_said = Waiting_for_user_input(filename)) {
  236. X      if (user_said == SEND) {
  237. X         io->xpr_filename = filename;
  238. X         XProtocolSend(io);
  239. X      }
  240. X      else if (user_said == RECEIVE) {
  241. X         io->xpr_filename = filename;
  242. X         XProtocolReceive(io);
  243. X      }
  244. X      else if (user_said == INITIALIZE) {
  245. X         io->xpr_filename = NULL;
  246. X         XProtocolSetup(io);
  247. X      }
  248. X   }
  249. X
  250. X   XProtocolCleanup(io);
  251. X
  252. X   CloseLibrary(XProtocolBase);
  253. X
  254. X   exit(0);
  255. X}
  256. X
  257. X        Clearly, only one FTP can be active at any particular instant in the
  258. Xlife of the session of the communications program. However, this is not really a
  259. Xlimitation in practice, and can be worked around at the cost of some amount of
  260. Xprogramming effort.
  261. X        XProtocolSetup(), XProtocolSend(), XProtocolReceive() and
  262. XXProtocolCleanup() return 0L on failure, non-zero on success.
  263. X
  264. X
  265. X
  266. X
  267. X3. The XPR_IO structure.
  268. X========================
  269. X
  270. X        The XPR_IO structure definition is given in Appendix B. The reader
  271. Xshould keep in mind that the callback functions are to be implemented by the
  272. Xauthor of the communications program, not by the author of the external
  273. Xprotocol. However, most communications programs already have functions that
  274. Xperform the operations listed here, so the implementation should not be too
  275. Xdifficult. Also, the communications program author is not required, strictly
  276. Xspeaking, to implement any of the functions: functions that are not implemented
  277. Xshould be indicated by initializing the corresponding XPR_IO field to NULL.
  278. XObviously, a minimum set of functions must be implemented in order to be useful.
  279. XOn the other hand, it is up to the implementer of the external protocol to
  280. Xdetermine if the given set of functions is sufficient to perform the protocol
  281. Xtransfer. In case of missing functions (indicated by NULL fields in the XPR_IO
  282. Xstructure) suitable default actions should be taken.
  283. X
  284. X        We will now examine all the fields of XPR_IO in detail. 
  285. X
  286. X
  287. X3.1     char  *xpr_filename;
  288. X----------------------------
  289. X
  290. X        The xpr_filename field is used primarily to pass null-terminated strings
  291. Xcontaining a file name (or file names specified by wild cards) to the functions
  292. XXProtocolSend() or XProtocolReceive(). The XPR implementer may elect to support
  293. Xwild cards in the file name. Call-backs for finding the first and next filename
  294. Xmatching the pattern are provided in the XPR_IO structure, but on the other hand
  295. XXPR implementers should take care to check that these call-backs are implemented
  296. Xby the communications program by testing the corresponding XPR_IO fields for
  297. XNULL. Never assume that all call-backs are implemented! If a particular
  298. Xcall-back without which the XPR cannot function is not implemented, the XPR
  299. Xshould fail gracefully.
  300. X
  301. X        The xpr_filename field can also be used to pass an initialization string
  302. Xto XProtocolSetup(). Typically, if this field is left NULL in a call to
  303. XXProtocolSetup(), it would be the duty of XProtocolSetup() to query the user for
  304. Xinitialization information, using the xpr_gets function (see later). If an
  305. Xinitialization string is present, XProtocolSetup() should NOT query the user,
  306. Xbut this is left to the discretion of the implementer of the protocol, as is the
  307. Xprecise form of the initialization string. It is the duty of the communications
  308. Xprogram to determine any default initialization strings for the protocol in
  309. Xquestion. Suggested is the use of environment variables named for the protocols
  310. Xthey refer to, containing the initialization string. For the simple Ascii
  311. Xprotocol shown later, the user might have a statement like
  312. X
  313. X        set xprascii=50
  314. X
  315. Xin his startup sequence, or with AmigaDOS 1.3, a file called xprascii in his
  316. Xenv: directory containing the letters "50" (50 referring here to the number of
  317. Xticks delay between 80-character packets - obviously more extensive
  318. Xinitialization might be needed).
  319. X        Given the presence of such default information, XProtocolSetup() should
  320. Xalways be called using the default initialization string right after opening the
  321. Xlibrary. Conversely, a mechanism (menu option) should be present in the
  322. Xcommunications program to change the settings by calling XProtocolSetup() with a
  323. XNULL value for this field. On the other hand, if no default initialization
  324. Xstring is present, the legal situation can arise that XProtocolSetup() is never
  325. Xcalled.
  326. X        It should be noted that XProtocolSetup() can be used to implement any
  327. Xcommands not directly related to sending or receiving files. Examples that come
  328. Xto mind are Kermit Bye and Finish. One should keep in mind, that typically the
  329. Xcommunications program does not know what protocol it is running, much less what
  330. Xcommands that protocol might support. When the user asks to "setup" the external
  331. Xprotocol, XProtocolSetup() should be called with a NULL xpr_filename field,
  332. Xand the external protocol should request a command, as stated before. In the
  333. Xcase of an external Kermit protocol, the user might type a Bye or Finish, and
  334. Xthe external protocol could act accordingly.
  335. X
  336. X        The xpr_filename field is ignored by the XProtocolCleanup() function.
  337. X
  338. X
  339. X3.2    long (*xpr_fopen)();
  340. X---------------------------
  341. X
  342. X        The xpr_fopen() call-back function works in most respects identically to
  343. Xthe stdio function fopen(). Calling sequence:
  344. X
  345. X        long fp = (*xpr_fopen)(char *filename, char *accessmode)
  346. X        D0                     A0              A1
  347. X
  348. XThe result is a FILE structure, but one should not count on it being a
  349. Xparticular one, since it may be compiler dependent. The return value should only
  350. Xbe used in calls to other stdio functions. The only accesmodes available are
  351. X"r"  (read-only)
  352. X"w"  (write-only, create new file if none exists, truncate existing file)
  353. X"a"  (write-only, create new file if none exists, append to existing file)
  354. X"r+" (same as "r", but may also write)
  355. X"w+" (same as "w", but may also read)
  356. X"a+" (same as "a", but may also read).
  357. X        An error return is indicated when the function returns NULL.
  358. X        Note that the arguments must be passed in registers A0 and A1
  359. Xrespectively. See also section 4.
  360. X
  361. X
  362. X3.3     long (*xpr_fclose)();
  363. X-----------------------------
  364. X
  365. X        The xpr_fclose() call-back function works in most respects identically
  366. Xto the stdio function fclose(). Calling sequence:
  367. X
  368. X        (*xpr_fclose)(long filepointer)
  369. X                      A0
  370. X
  371. XNote that the argument must be passed in register A0.
  372. X
  373. X
  374. X3.4     long (*xpr_fread)();
  375. X----------------------------
  376. X
  377. X        The xpr_fread() call-back function works in most respects identically to
  378. Xthe stdio function fread(). Calling sequence:
  379. X
  380. X        long count = (*xpr_fread)(char *buffer, long size, long count,
  381. X        D0                        A0            D0         D1
  382. X
  383. X                                  long fileptr)
  384. X                                  A1
  385. X
  386. XThe function returns the actual number items read. The size argument is in bytes.
  387. XThe function returns 0 on error or end of file.
  388. X
  389. X
  390. X3.5     long (*xpr_fwrite)();
  391. X-----------------------------
  392. X
  393. X        The xpr_fwrite() call-back function works in most respects identically
  394. Xto the stdio function fwrite(). Calling sequence:
  395. X
  396. X        long count = (*xpr_fwrite)(char *buffer, long size, long count,
  397. X        D0                         A0            D0         D1
  398. X
  399. X                                  long fileptr)
  400. X                                  A1
  401. X
  402. XThe function returns the actual number items written. The size argument is in
  403. Xbytes. The function returns 0 on failure.
  404. X
  405. X
  406. X3.6     long (*xpr_sread)();
  407. X----------------------------
  408. X
  409. X        The xpr_sread() call-back function has the following calling sequence:
  410. X
  411. X        long count = (*xpr_sread)(char *buffer, long size, long timeout)
  412. X        D0                        A0            D0         D1
  413. X
  414. XThe first argument is a pointer to a buffer to receive the characters from the
  415. Xserial port, with a size specified in the second argument. The third item is a
  416. Xtimeout in microseconds. The timeout may be set to 0L if the objective is to
  417. Xjust read any characters that may currently be available. When this argument is
  418. Xnon-zero, the function will not return until either the timeout period has
  419. Xexpired, or the buffer has filled up. The function returns the actual number of
  420. Xcharacters put into the buffer, or -1L on error or timeout.
  421. X        Note: the value 0L for the timeout argument is a special case. Remember
  422. Xthat AmigaDOS 1.3 may have problems with small non-zero values for timeouts.
  423. X
  424. X
  425. X3.7     long (*xpr_swrite)();
  426. X-----------------------------
  427. X
  428. X        The xpr_swrite() call-back function has the following calling sequence:
  429. X
  430. X        long status = (*xpr_swrite)(char *buffer, long size)
  431. X        D0                          A0            D0
  432. X
  433. XThis function writes a buffer with the given size to the serial port. It returns
  434. X0L on success, non-zero on failure.
  435. X
  436. X3.8     long (*xpr_sflush)();
  437. X----------------------------
  438. X
  439. X        The xpr_sflush call-back function has the following calling sequence:
  440. X
  441. X        long status = (*xpr_sflush)()
  442. X        D0
  443. X
  444. XThis function flushes all the data in the serial port input buffer.  It is
  445. Xtypically used to recover after a protocol error. The function returns 0L on
  446. Xsuccess, non-zero on failure.
  447. X
  448. X3.9     long (*xpr_update)();
  449. X-----------------------------
  450. X
  451. X        The xpr_update() call-back function has the following calling sequence:
  452. X
  453. X        (*xpr_update)(struct XPR_UPDATE *updatestruct)
  454. X                      A0
  455. Xwhere:
  456. X
  457. Xstruct XPR_UPDATE {     long  xpru_updatemask;
  458. X                        char *xpru_protocol;
  459. X                        char *xpru_filename;
  460. X                        long  xpru_filesize;
  461. X                        char *xpru_msg;
  462. X                        char *xpru_errormsg;
  463. X                        long  xpru_blocks;
  464. X                        long  xpru_blocksize;
  465. X                        long  xpru_bytes;
  466. X                        long  xpru_errors;
  467. X                        long  xpru_timeouts;
  468. X                        long  xpru_packettype;
  469. X                        long  xpru_packetdelay;
  470. X                        long  xpru_chardelay;
  471. X                        char *xpru_blockcheck;
  472. X                        char *xpru_expecttime;
  473. X                        char *xpru_elapsedtime;
  474. X                        long  xpru_datarate;
  475. X                        long  xpru_reserved1;
  476. X                        long  xpru_reserved2;
  477. X                        long  xpru_reserved3;
  478. X                        long  xpru_reserved4;
  479. X                        long  xpru_reserved5;
  480. X                   }
  481. X
  482. XThis function is intended to communicate a variety of values and strings from
  483. Xthe external protocol to the communications program for display. Hence, the
  484. Xdisplay format itself (requester, text-I/O) is left to the implementer of the
  485. Xcommunications program.
  486. X        The mask xpru_updatemask indicates which of the other fields are valid,
  487. Xi.e. have had their value updated. It is possible to update a single or multiple
  488. Xvalues. Values that the external protocol does not use can be indicated by a
  489. XNULL for pointers and -1L for longs.
  490. X        The possible bit values for the xpru_updatemask are:
  491. X
  492. X                #define XPRU_PROTOCOL           0x00000001L
  493. X                #define XPRU_FILENAME           0x00000002L
  494. X                #define XPRU_FILESIZE           0x00000004L
  495. X                #define XPRU_MSG                0x00000008L
  496. X                #define XPRU_ERRORMSG           0x00000010L
  497. X                #define XPRU_BLOCKS             0x00000020L
  498. X                #define XPRU_BLOCKSIZE          0x00000040L
  499. X                #define XPRU_BYTES              0x00000080L
  500. X                #define XPRU_ERRORS             0x00000100L
  501. X                #define XPRU_TIMEOUTS           0x00000200L
  502. X                #define XPRU_PACKETTYPE         0x00000400L
  503. X                #define XPRU_PACKETDELAY        0x00000800L
  504. X                #define XPRU_CHARDELAY          0x00001000L
  505. X                #define XPRU_BLOCKCHECK         0x00002000L
  506. X                #define XPRU_EXPECTTIME         0x00004000L
  507. X                #define XPRU_ELAPSEDTIME        0x00008000L
  508. X                #define XPRU_DATARATE           0x00010000L
  509. X
  510. X        The other fields of the XPR_UPDATE structure have the following
  511. Xmeaning:
  512. X
  513. Xxpru_protocol    -- a string that indicates the name of the protocol used
  514. Xxpru_filename    -- the name of the file currently sent or received
  515. Xxpru_filesize    -- the size of the file
  516. Xxpru_msg         -- a "generic" message (50 characters or less)
  517. Xxpru_errormsg    -- an "error" message  (50 characters or less)
  518. Xxpru_blocks      -- number of transferred blocks
  519. Xxpru_blocksize   -- size of most recently transferred block (bytes)
  520. Xxpru_bytes       -- number of transferred bytes
  521. Xxpru_errors      -- number of errors
  522. Xxpru_timeouts    -- number of timeouts
  523. Xxpru_packettype  -- type of packet (e.g. Kermit 'D'-packet)
  524. Xxpru_packetdelay -- delay between packets in msec
  525. Xxpru_chardelay   -- delay between characters in msec
  526. Xxpru_blockcheck  -- block check type (e.g. "Checksum", "CRC-16", "CRC-32")
  527. Xxpru_expecttime  -- expected transfer time (e.g. "5 min 20 sec", "00:05:30")
  528. Xxpru_elapsedtime -- elapsed time from start of transfer (see xpru_expecttime)
  529. Xxpru_datarate    -- rate of data transfer expressed in characters per second.
  530. Xxpru_reserved1   -- for further expansion
  531. X ...         .   --  ...
  532. Xxpru_reserved5   -- for further expansion
  533. X
  534. X        The communications program is free to ignore any field and to only update
  535. Xthe ones it can handle.
  536. X        If xpru_updatemask is equal to -1L, then ALL fields are either valid or 
  537. Xare unambiguously valued to indicate they are unused: NULL for pointers and -1L
  538. Xfor longs.
  539. X        When writing an external protocol, it is advisable to keep any strings
  540. Xas short as possible, and not longer than about 50 characters. Remember, if your
  541. Xstrings are too long, they may overflow whatever display mechanism the
  542. Xcommunications program has chosen. It is also advisable to fill in as many
  543. Xfields as you can, since the communications program may not choose to display
  544. Xthe ones you favor. When writing a communications program interface to XPR, on
  545. Xthe other hand, remember that strings can be as much as 50 characters long. If
  546. Xyou don't receive your favorite variables, it may be possible to compute them
  547. Xfrom those that are given. It is good practice for the external protocol to call
  548. Xxpr_update before starting the transfer with a message in the xpru_msg field
  549. Xindicating whether the protocol is sending or receiving a file.
  550. X        The XPR_UPDATE structure must be provided by the external protocol, and
  551. Xmust, of course be allocated either on the stack (as a local variable) or using
  552. XAllocMem or malloc(). This is needed to ensure reentrancy. In general, it is a
  553. Xgood idea to keep the entire library reentrant, since more than one
  554. Xcommunications program may be using the same code simultaneously.
  555. X
  556. X
  557. X3.10     long (*xpr_chkabort)();
  558. X-------------------------------
  559. X
  560. X        The xpr_chkabort() call-back function has no arguments:
  561. X
  562. X        long status = (*xpr_chkabort)()
  563. X        D0
  564. X
  565. XWhen it returns non-zero, it means that the user has requested an abort. It is
  566. Xpossible to implement levels of abort by returning 1L, 2L, 3L, etc, depending on
  567. Xthe user's actions. The highest level of abort is -1L, which should be
  568. Xinterpreted to mean stop all actions and return. The chkabort function should be
  569. Xcalled reasonably frequently.
  570. X
  571. X
  572. X3.11    long (*xpr_chkmisc)();
  573. X------------------------------
  574. X
  575. X        The xpr_chkmisc() call-back function has no arguments and returns
  576. Xnothing.
  577. X
  578. X        (*xpr_chkmisc)()
  579. X
  580. XIt is intended to give the communications program that is currently executing
  581. Xthe external protocol transfer a chance to service its various message ports and
  582. Xto respond to user actions. It should be called on a regular basis.
  583. X
  584. X
  585. X3.12    long (*xpr_gets)();
  586. X---------------------------
  587. X
  588. X        The xpr_gets() call-back function works somewhat like the stdio function
  589. Xgets(). Calling sequence:
  590. X
  591. X        long status = (*xpr_gets)(char *prompt, char *buffer)
  592. X        D0                        A0            A1
  593. X
  594. XThe first argument is a pointer to a string containing a prompt, to be displayed
  595. Xby the communications program in any manner it sees fit. The second argument
  596. Xshould be a pointer to a buffer to receive the user's response. It should have a
  597. Xsize of at least 256 bytes. The function returns 0L on failure or user
  598. Xcancellation, non-zero on success. The buffer has to be supplied by the XPR.
  599. X
  600. X
  601. X3.13    long (*xpr_setserial)();
  602. X--------------------------------
  603. X
  604. X        The xpr_setserial() call-back function has the following calling
  605. Xsequence:
  606. X
  607. X        long oldstatus = (*xpr_setserial)(long newstatus)
  608. X        D0                                D0
  609. X
  610. XThis function returns the current serial device status in encoded form. If the
  611. Xnewstatus argument is -1L, the serial device status will not be changed.
  612. XOtherwise the serial device status will be changed to newstatus. If oldstatus
  613. Xis returned as -1L, the call failed and the serial status was not changed.
  614. X        Note: if the serial device status is changed with this function, the 
  615. Xexternal protocol must change the status back to oldstatus before returning.
  616. X
  617. X        serial status longword:
  618. X        .......................
  619. X
  620. X        byte 0:         as the SerFlags field in IOExtSer structure.
  621. X                bit 0:  - parity on if set
  622. X                bit 1:  - parity odd if set
  623. X                bit 2:  - 7-wire protocol enabled if set
  624. X                bit 3:  - queued break if set
  625. X                bit 4:  - rad-boogie if set
  626. X                bit 5:  - shared if set
  627. X                bit 6:  - EOF mode if set
  628. X                bit 7:  - Xon/Xoff disabled if set
  629. X        byte 1:         summary of other settings
  630. X                bit 0:  - enable mark/space parity if set
  631. X                bit 1:  - parity mark if set, space otherwise
  632. X                bit 2:  - 2 stop bits if set, 1 otherwise
  633. X                bit 3:  - read wordlength is 7 if set, 8 otherwise
  634. X                bit 4:  - write wordlength is 7 if set, 8 otherwise
  635. X                bit 5:  - not used
  636. X                bit 6:  - not used
  637. X                bit 7:  - not used
  638. X        byte 2:         specifies one of a limited set of baud rates, as in
  639. X                        preferences.h.
  640. X                        -    110 baud =  0
  641. X                        -    300 baud =  1
  642. X                        -   1200 baud =  2
  643. X                        -   2400 baud =  3
  644. X                        -   4800 baud =  4
  645. X                        -   9600 baud =  5
  646. X                        -  19200 baud =  6
  647. X                        -   midi      =  7
  648. X                        -  38400 baud =  8
  649. X                        -  57600 baud =  9
  650. X                        -  76800 baud = 10
  651. X                        - 115200 baud = 11
  652. X        byte 3:         not used
  653. X
  654. X
  655. X3.14    long (*xpr_ffirst)();
  656. X-----------------------------
  657. X
  658. X        The xpr_ffirst() call-back function has the calling sequence:
  659. X
  660. X        long stateinfo = (*xpr_ffirst)(char *buffer, char *pattern)
  661. X        D0                             A0            A1
  662. X
  663. XThe first argument is a buffer to receive the first filename that matches the
  664. Xpattern in the second argument. The function returns 0L if no file matching the
  665. Xpattern was found, non-zero otherwise. The buffer should have a size of at least
  666. X256 bytes and is provided by the XPR. See also 3.14.
  667. X
  668. X
  669. X3.15    long (*xpr_fnext)();
  670. X----------------------------
  671. X
  672. X        The xpr_fnext() call-back function has the calling sequence:
  673. X
  674. X        long stateinfo = (*xpr_fnext)(long oldstate, char *buffer, char *pattern)
  675. X        D0                            D0             A0            A1
  676. X
  677. XThe first argument is a buffer to receive the next filename that matches the
  678. Xpattern in the second argument. The function returns 0L if no further file
  679. Xmatching the pattern was found, non-zero otherwise. The buffer should have a
  680. Xsize of at least 256 bytes and is provided by the XPR.
  681. X        Note: the value returned by xpr_ffirst and xpr_fnext may be used by the
  682. Ximplementing communications program to maintain state information, but the
  683. Xmechanism is up to the implementer. If reentrancy is not required, state
  684. Xinformation may be kept in global variables by the implementer, and the oldstate
  685. Xargument can be ignored. However, the external protocol implementation must pass
  686. Xthe stateinfo variable returned by ffirst or fnext to the next invocation of
  687. Xfnext.
  688. X
  689. X
  690. X3.16    long (*xpr_finfo)();
  691. X----------------------------
  692. X
  693. X        The xpr_finfo() call-back function has the calling sequence:
  694. X
  695. X        long info = (*xpr_finfo)(char *filename, long typeofinfo)
  696. X        D0                       A0              D0
  697. X
  698. XThis function returns information about a file given its name and the type of
  699. Xinformation requested. Notice that some information may not be accessible if
  700. Xthe file is already write locked. Therefore, you should call this function
  701. X(where appropriate) before opening the file.
  702. X
  703. X        typeofinfo value:       resulting info:              on failure:
  704. X        ..................................................................
  705. X
  706. X        1L                      file size (bytes)            0L
  707. X
  708. X        2L                      file type: 1L is binary,     0L
  709. X                                           2L is text.
  710. X
  711. X        (other values)          (to be determined)
  712. X
  713. X
  714. X3.17    long  *xpr_fseek();
  715. X---------------------------
  716. X
  717. X        The xpr_fseek() call-back function works in most respects identically to
  718. Xthe stdio function fseek(). Calling sequence:
  719. X
  720. X        long status = (*xpr_fseek)(long fileptr, long offset, long origin)
  721. X        D0                         A0            D0           D1
  722. X
  723. XThis function sets the current position of a file to "offset" from the 
  724. Xbeginning (origin = 0), current position (origin = 1) or end (origin = 2) of
  725. Xthe file.
  726. XThe function returns 0 on success.
  727. X
  728. X
  729. X3.18    long  *xpr_extension;
  730. X-----------------------------
  731. X
  732. X        This field indicates how many extension fields follow this structure.
  733. XBefore using any functions or fields defined in section 3.20 and later, the
  734. XXPR must check that the desired function is indeed present by ensuring that
  735. Xxpr_extension is larger than the position of the function beyond the xpr_data
  736. Xfield.
  737. X
  738. X
  739. X3.19    long  *xpr_data;
  740. X------------------------
  741. X
  742. X        This field is for internal use by the external protocol. Typically the
  743. Xfield is initialized to point to a structure containing information extracted
  744. Xfrom the initialization string handed to or retrieved by the XProtocolSetup()
  745. Xfunction, see section 2. The structure should be deallocated and the field
  746. Xrestored to NULL by the XProtocolCleanup() function. The communications program
  747. Xshould never access this field, except when initializing the XPR_IO structure:
  748. Xthe field should be initialized to NULL.
  749. X
  750. X
  751. X3.20    long  *xpr_options();
  752. X-----------------------------
  753. X
  754. X        This function is in the first extension field of the XPR_IO structure.
  755. XOnly use this function if the value of the xpr_extension field is 1L or larger.
  756. XThe calling sequence is:
  757. X
  758. X        long status = (*xpr_options)(long n, struct xpr_option *opt[])
  759. X        D0                           D0      A0
  760. X
  761. XThe function passes to the comm program a pointer to an array of n xpr_option
  762. Xstructures, where n is limited to 31. The xpr_option structures are defined as
  763. Xfollows:
  764. X
  765. Xstruct xpr_option {
  766. X   char *xpro_description;      /* description of the option                  */
  767. X   long  xpro_type;             /* type of option                             */
  768. X   char *xpro_value;            /* pointer to a buffer with the current value */
  769. X   long  xpro_length;           /* buffer size                                */
  770. X}
  771. X
  772. XValid values for xpro_type are:
  773. X
  774. X#define XPRO_BOOLEAN 1L         /* xpro_value is "yes", "no", "on" or "off"   */
  775. X#define XPRO_LONG    2L         /* xpro_value is string representing a number */
  776. X#define XPRO_STRING  3L         /* xpro_value is a string                     */
  777. X
  778. X        The array is allocated and initialized by the XPR to default values. If
  779. Xthe comm program implements this function, it should display the description of
  780. Xthe option and its current value to the user and allow him/her to change them.
  781. XThis could be accomplished either by dynamically building a requester or by
  782. Xdisplaying each line one at a time and allow the user to enter new values or
  783. Xaccept the default. Options that have boolean values could be implemented by the
  784. Xcomm program as boolean gadgets, but the new value must be returned as "yes" or
  785. X"on" for logical 1 or "no" or "off" for logical 0 in the xpro_value buffer, and
  786. Xthat long values must be converted to a string and copied to the xpro_value
  787. Xbuffer. Note, that the XPR, if it uses this function must recognize both "yes"
  788. Xand "on" for logical 1 and "no" and "off" for logical 0. For options that have
  789. Xstring values, the comm program must ensure that the new string selected by the
  790. Xuser fits in the value buffer as determined by the xpro_length field. The buffer
  791. Xis supplied by the XPR.
  792. X        For example, when selecting a ZMODEM based XPR the following array of
  793. Xxpr_option structures could be passed to the comm program:
  794. X
  795. Xxpro_description                xpro_value    xpro_type
  796. X--------------------------------------------------------------
  797. XConvert NL to NL/CR             no            XPRO_BOOLEAN
  798. XEscape only CTRL chars          yes           XPRO_BOOLEAN
  799. XEscape ALL chars                no            XPRO_BOOLEAN
  800. XSend full pathname              yes           XPRO_BOOLEAN
  801. XSend 1K blocks                  no            XPRO_BOOLEAN
  802. XSubpacket length                512           XPRO_LONG
  803. XDisable 32-bit CRC              no            XPRO_BOOLEAN
  804. XProtect destination file        no            XPRO_BOOLEAN
  805. XTimeout value (sec)             10            XPRO_LONG
  806. XDelete after transmission       no            XPRO_BOOLEAN
  807. XOverwrite existing file         no            XPRO_BOOLEAN
  808. X
  809. XNotice again, that the COMM program still knows nothing about the individual
  810. Xoption items (and in fact there is no way for it to find out, in keeping with
  811. Xthe philosophy of XPR). Also notice that a cheap way to implement this function
  812. Xis to loop over the n supplied xpr_option's and to call the likely already
  813. Ximplemented xpr_gets function with the option description and the value buffer.
  814. X        It is important to follow a few rules when calling this function: the
  815. Xdescription strings should be 25 characters or less. The value strings can be
  816. Xany length up to 255 characters, but be aware that in a typical situation only
  817. Xabout 10 to 15 of them will be displayed in a string requester.
  818. X        The return value, status, reflects which options have changed by having
  819. Xthe corresponding bit set. The first option in the xpr_option array corresponds
  820. Xto  bit 0 (low-order), etc. If the comm program decides to not detect whether
  821. Xthe options changed or not, 0x07FFFFFFL may be returned, in effect specifying
  822. Xthat all options have changed. If nothing changed, 0L is returned. If an error
  823. Xoccurred, the function returns -1L.
  824. X
  825. X
  826. X
  827. X
  828. X4. An example protocol.
  829. X=======================
  830. X
  831. X        The following is an annotated listing of an ascii upload protocol.
  832. XNotice that the files supplied in this archive are likely more up to date and
  833. Xmore extensive than the example given here.
  834. X
  835. X/** xprascii.c
  836. X*
  837. X*   These are the protocol transfer routines for a simple ASCII upload.
  838. X*
  839. X**/
  840. X#include <exec/exec.h>
  841. X#include <functions.h>
  842. X#include <stdio.h>
  843. X/*
  844. X*   xproto.h is the include file given in Appendix B.
  845. X*/
  846. X#include "xproto.h"
  847. X/*
  848. X*   The following two strings must exist.
  849. X*/
  850. Xchar  XPRname[]   = "xprascii.library";
  851. Xchar  XPRid[]     = "xprascii 0.9 (May 89)\r\n";
  852. XUWORD XPRrevision = 9;
  853. X
  854. Xlong atol();
  855. X/*
  856. X*   The callxx...() routines are described later. They provide the 
  857. X*   assembler interface from the XPR library to the call-back routines.
  858. X*/
  859. Xlong calla(), callaa(), callad(), calladd(), calladda();
  860. X
  861. Xchar *malloc();
  862. X
  863. X
  864. X/**
  865. X*
  866. X*   Send a file
  867. X*
  868. X**/
  869. Xlong XProtocolSend(IO)
  870. Xstruct XPR_IO *IO;
  871. X{
  872. X   long fp, r, i;
  873. X   long brkflag = 0, fl = 0L, sd = 0L;
  874. X   long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfread)(),
  875. X        (*xsread)(),  (*xchkabort)();
  876. X   unsigned char *buff = NULL, *serbuff = NULL;
  877. X   struct XPR_UPDATE xpru;
  878. X
  879. X/*
  880. X*   These are the call-backs we need. If any of them isn't provided, quit.
  881. X*   Could do some error reporting if at least xupdate is there.
  882. X*/
  883. X   if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  884. X   if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  885. X   if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  886. X   if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  887. X   if ((xfread     = IO->xpr_fread)    == NULL) return(0L);
  888. X   if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  889. X   if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  890. X/*
  891. X*   Allocate a few buffers.
  892. X*/
  893. X   buff    = (unsigned char *) malloc(80);
  894. X   serbuff = (unsigned char *) malloc(80);
  895. X/*
  896. X*   If we ran out of memory, print a message.
  897. X*   The argument needs to go in A0: calla does this for us. 
  898. X*/
  899. X   if (buff == NULL || serbuff == NULL) {
  900. X      xpru.xpru_updatemask = XPRU_ERRORMSG;
  901. X      xpru.xpru_errormsg   = "Ran out of memory!";
  902. X      calla(xupdate, &xpru);
  903. X      return(0L);
  904. X   }
  905. X/*
  906. X*   Read the send delay, if a XProtocolSetup() was done before.
  907. X*   If send delay is too large, cut it off at 10 seconds.
  908. X*   In this example, the xpr_data field contains a null terminated string
  909. X*   containing the number of ticks to delay each 80 characters.
  910. X*/
  911. X   if (IO->xpr_data) {
  912. X      sd = atol(IO->xpr_data);
  913. X      if (sd > 500L) sd = 500L;
  914. X   }
  915. X/*
  916. X*   Open the file. One could do wild card detection here.
  917. X*   xfopen requires two arguments, in a0 and a1 respectively.
  918. X*   Again, this must be done in assembler, and callaa does it.
  919. X*/
  920. X   fp = callaa(xfopen, IO->xpr_filename, "r");
  921. X   if (fp == NULL) {
  922. X      free(buff);
  923. X      free(serbuff);
  924. X      xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  925. X      xpru.xpru_errormsg   = "Failed to open input file";
  926. X      xpru.xpru_filename   = IO->xpr_filename;
  927. X      calla(xupdate, &xpru);
  928. X      return(0L);
  929. X   }
  930. X/*
  931. X*   Start the transfer. See 3.8 for a discussion on how to implement
  932. X*   xupdate. 
  933. X*/
  934. X   xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  935. X   xpru.xpru_msg        = "Starting ASCII Send";
  936. X   xpru.xpru_filename   = IO->xpr_filename;
  937. X   calla(xupdate, &xpru);
  938. X/*
  939. X*   Now read 80 byte chunks from the file using xfread.
  940. X*   xfread requires four arguments, a0, d0, d1 and a1.
  941. X*/
  942. X   xpru.xpru_blocks = 0L;
  943. X   while (r = calladda(xfread, buff, 1L, 80L, fp)) {
  944. X/*
  945. X*   Convert line feeds to carriage returns before sending to host.
  946. X*   fl counts the characters. Display how many characters are sent.
  947. X*/
  948. X      for (i = 0L; i < r; i++) if (buff[i] == '\n') buff[i] = '\r';
  949. X      fl += r;
  950. X      xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  951. X      xpru.xpru_bytes      = fl;
  952. X      xpru.xpru_blocks++;
  953. X      xpru.xpru_blocksize  = r;
  954. X      calla(xupdate, &xpru);
  955. X      callad(xswrite, buff, r);
  956. X/*
  957. X*   Every 80 bytes, put out a message and delay if requested.
  958. X*/
  959. X      xpru.xpru_updatemask  = XPRU_PACKETDELAY;
  960. X      xpru.xpru_packetdelay = sd * 20L;  /* msec! */
  961. X      calla(xupdate, &xpru);
  962. X/*
  963. X*   Can't use Delay() here, because Delay() is in dos.library!
  964. X*   However writing an equivalent function using the timer.device is
  965. X*   trivial.
  966. X*/
  967. X      TimeOut(sd);
  968. X/*
  969. X*   Eat any characters that might arrive from the serial port.
  970. X*   calladd stores arg1 in a0, arg2 in d0, arg3 in d1.
  971. X*   We're not really waiting for any characters: use a timeout of 0L.
  972. X*/
  973. X      while (calladd(xsread, serbuff, 80L, 0L) > 0L) ;
  974. X/*
  975. X*   Check for "abort" here. Perhaps should call chkmisc() as well.
  976. X*/
  977. X      if (brkflag = xchkabort()) break;
  978. X   }
  979. X/*
  980. X*   Close the file
  981. X*/
  982. X   calla(xfclose, fp);
  983. X   free(buff);
  984. X   free(serbuff);
  985. X/*
  986. X*   If we got here through chkabort() say Aborted.
  987. X*/
  988. X   xpru.xpru_updatemask       = XPRU_MSG;
  989. X   if (brkflag) xpru.xpru_msg = "Aborted";
  990. X   else         xpru.xpru_msg = "Done"; 
  991. X   calla(xupdate, &xpru);
  992. X   if (brkflag) return(0L);
  993. X   else         return(1L);
  994. X}
  995. X
  996. X
  997. X/**
  998. X*
  999. X*   Receive a file.
  1000. X*
  1001. X**/
  1002. Xlong XProtocolReceive(IO)
  1003. Xstruct XPR_IO *IO;
  1004. X{
  1005. X   long fp, r, i;
  1006. X   long brkflag = 0, fl = 0L, sd = 0L;
  1007. X   long (*xupdate)(), (*xswrite)(), (*xfopen)(), (*xfclose)(), (*xfwrite)(),
  1008. X        (*xsread)(),  (*xchkabort)();
  1009. X   unsigned char *serbuff = NULL;
  1010. X   struct XPR_UPDATE xpru;
  1011. X
  1012. X/*
  1013. X*   These are the call-backs we need. If any of them isn't provided, quit.
  1014. X*   Could do some error reporting if at least xupdate is there.
  1015. X*/
  1016. X   if ((xupdate    = IO->xpr_update)   == NULL) return(0L);
  1017. X   if ((xswrite    = IO->xpr_swrite)   == NULL) return(0L);
  1018. X   if ((xfopen     = IO->xpr_fopen)    == NULL) return(0L);
  1019. X   if ((xfclose    = IO->xpr_fclose)   == NULL) return(0L);
  1020. X   if ((xfwrite    = IO->xpr_fwrite)   == NULL) return(0L);
  1021. X   if ((xsread     = IO->xpr_sread)    == NULL) return(0L);
  1022. X   if ((xchkabort  = IO->xpr_chkabort) == NULL) return(0L);
  1023. X/*
  1024. X*   Allocate a buffer.
  1025. X*/
  1026. X   serbuff = (unsigned char *) malloc(80);
  1027. X/*
  1028. X*   If we ran out of memory, print a message.
  1029. X*   The argument needs to go in A0: calla does this for us. 
  1030. X*/
  1031. X   if (serbuff == NULL) {
  1032. X      xpru.xpru_updatemask = XPRU_ERRORMSG;
  1033. X      xpru.xpru_errormsg   = "Ran out of memory!";
  1034. X      calla(xupdate, &xpru);
  1035. X      return(0L);
  1036. X   }
  1037. X/*
  1038. X*   Open the file.
  1039. X*   xfopen requires two arguments, in a0 and a1 respectively.
  1040. X*   Again, this must be done in assembler, and callaa does it.
  1041. X*/
  1042. X   fp = callaa(xfopen, IO->xpr_filename, "w");
  1043. X   if (fp == NULL) {
  1044. X      free(serbuff);
  1045. X      xpru.xpru_updatemask = XPRU_ERRORMSG | XPRU_FILENAME;
  1046. X      xpru.xpru_errormsg   = "Failed to open output file";
  1047. X      xpru.xpru_filename   = IO->xpr_filename;
  1048. X      calla(xupdate, &xpru);
  1049. X      return(0L);
  1050. X   }
  1051. X/*
  1052. X*   Start the transfer. See 3.8 for a discussion on how to implement
  1053. X*   xupdate. 
  1054. X*/
  1055. X   xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  1056. X   xpru.xpru_msg        = "Starting ASCII Receive";
  1057. X   xpru.xpru_filename   = IO->xpr_filename;
  1058. X   calla(xupdate, &xpru);
  1059. X/*
  1060. X*   Now read 80 byte chunks from the serial port using xsread. Stop
  1061. X*   when no characters arrive for 5 sec.
  1062. X*/
  1063. X   xpru.xpru_blocks = 0L;
  1064. X   while ((r = calladd(xsread, serbuff, 80L, 5000000L)) > 0L)  {
  1065. X/*
  1066. X*   Strip high-bit before storing in file.
  1067. X*   fl counts the characters. Display how many characters are received.
  1068. X*/
  1069. X      for (i = 0L; i < r; i++) serbuff[i] &= 0177;
  1070. X      fl += r;
  1071. X      xpru.xpru_updatemask = XPRU_BYTES | XPRU_BLOCKS | XPRU_BLOCKSIZE;
  1072. X      xpru.xpru_bytes      = fl;
  1073. X      xpru.xpru_blocks++;
  1074. X      xpru.xpru_blocksize  = r;
  1075. X      calla(xupdate, &xpru);
  1076. X/* 
  1077. X*   Write 80 byte chunks to the file using xwrite
  1078. X*/
  1079. X      calladda(xfwrite, serbuff, 1L, r, fp);
  1080. X
  1081. X/*
  1082. X*   Check for "abort" here. Perhaps should call chkmisc() as well.
  1083. X*/
  1084. X      if (brkflag = xchkabort()) break;
  1085. X   }
  1086. X/*
  1087. X*   Close the file
  1088. X*/
  1089. X   calla(xfclose, fp);
  1090. X   free(serbuff);
  1091. X/*
  1092. X*   If we got here through chkabort() say Aborted.
  1093. X*/
  1094. X   xpru.xpru_updatemask       = XPRU_MSG;
  1095. X   if (brkflag) xpru.xpru_msg = "Aborted";
  1096. X   else         xpru.xpru_msg = "Done"; 
  1097. X   calla(xupdate, &xpru);
  1098. X   if (brkflag) return(0L);
  1099. X   else         return(1L);
  1100. X}
  1101. X
  1102. X
  1103. X/**
  1104. X*
  1105. X*   Setup
  1106. X*
  1107. X**/
  1108. Xlong XProtocolSetup(IO)
  1109. Xstruct XPR_IO *IO;
  1110. X{
  1111. X   long (*xupdate)(), (*xgets)();
  1112. X   struct XPR_UPDATE xpru;
  1113. X
  1114. X   if ((xupdate = IO->xpr_update) == NULL) return(0L);
  1115. X   if ((xgets   = IO->xpr_gets)   == NULL) return(0L);
  1116. X/*
  1117. X*   Allocate a bit of memory for a data buffer
  1118. X*/
  1119. X   if (IO->xpr_data == NULL) {
  1120. X      if ((IO->xpr_data = (long *) malloc(256)) == NULL) {
  1121. X         xpru.xpru_updatemask = XPRU_ERRORMSG;
  1122. X         xpru.xpru_errormsg   = "ASCII - Out of memory!";
  1123. X         calla(xupdate, &xpru);
  1124. X         return(0L);
  1125. X      }
  1126. X   }
  1127. X/*
  1128. X*   If setup string isn't handed to us, ask questions
  1129. X*/
  1130. X   if (IO->xpr_filename == NULL) {
  1131. X/*
  1132. X*   Get the value for the send dealy
  1133. X*/
  1134. X      callaa(xgets, "Enter ASCII send delay (ticks, 1 tick = 20 msec)",
  1135. X                  IO->xpr_data);
  1136. X   }
  1137. X   else {
  1138. X      strcpy(IO->xpr_data, IO->xpr_filename);
  1139. X   }
  1140. X   
  1141. X   return(1L);
  1142. X}
  1143. X
  1144. X/**
  1145. X*
  1146. X*   Cleanup
  1147. X*
  1148. X**/
  1149. Xlong XProtocolCleanup(IO)
  1150. Xstruct XPR_IO *IO;
  1151. X{
  1152. X   if (IO->xpr_data) free(IO->xpr_data);
  1153. X   IO->xpr_data = NULL;
  1154. X
  1155. X   return(1L);
  1156. X}
  1157. X
  1158. X/**
  1159. X*
  1160. X*   The following functions setup the proper registers for the call-back 
  1161. X*   functions.
  1162. X*
  1163. X**/
  1164. X#asm
  1165. X        public _callad
  1166. X_callad:
  1167. X        movea.l 8(sp),a0                ; Second argument goes in a0
  1168. X        move.l  12(sp),d0               ; Third  argument goes in d0
  1169. X/*
  1170. X*   Now this is a trick to avoid using another register.
  1171. X*   Charlie taught me this...
  1172. X*/
  1173. X        move.l  4(sp),-(sp)             ; First  argument is function
  1174. X        rts
  1175. X
  1176. X        public  _calladda
  1177. X_calladda:
  1178. X        movea.l 8(sp),a0                ; Second argument goes in a0
  1179. X        move.l  12(sp),d0               ; Third  argument goes in d0
  1180. X        move.l  16(sp),d1               ; Fourth argument goes in d1
  1181. X        movea.l 20(sp),a1               ; Fifth  argument goes in a1
  1182. X        move.l  4(sp),-(sp)             ; First  argument is function
  1183. X        rts
  1184. X
  1185. X        public  _calla
  1186. X_calla:
  1187. X        movea.l 8(sp),a0                ; Second argument goes in a0
  1188. X        move.l  4(sp),-(sp)             ; First  argument is function
  1189. X        rts
  1190. X
  1191. X        public  _callaa
  1192. X_callaa:
  1193. X        movea.l 8(sp),a0                ; Second argument goes in a0
  1194. X        movea.l 12(sp),a1               ; Third  argument goes in a1
  1195. X        move.l  4(sp),-(sp)             ; First  argument is function
  1196. X        rts
  1197. X
  1198. X        public  _calladd
  1199. X_calladd:
  1200. X        move.l  8(sp),a0                ; Second argument goes in a0
  1201. X        move.l  12(sp),d0               ; Third  argument goes in d0
  1202. X        move.l  16(sp),d1               ; Fourth argument goes in d1
  1203. X        move.l  4(sp),-(sp)             ; First  argument is function
  1204. X        rts
  1205. X
  1206. X#endasm
  1207. X/*
  1208. X*   Could have added any other functions needed for other call-backs.
  1209. X*   Could have written a fancier single one... Could've...
  1210. X*/
  1211. X                              __                
  1212. X                             /  \ o    /        
  1213. X                       -----/----\----/-----
  1214. X                           /    o \__/          
  1215. X                                                
  1216. X        Clearly it isn't very hard to implement a simple protocol. More
  1217. Xelaborate protocols are straightforward extensions to the above example. Of
  1218. Xcourse, there are a few more standard files needed to make the above example
  1219. Xinto a complete library (like Open, Close and Expunge functions and a ROM-Tag
  1220. Xstructure) but those parts are the same for any library and aren't given here.
  1221. X
  1222. X
  1223. X
  1224. X5. The interface to the communications program.
  1225. X===============================================
  1226. X
  1227. X        The following is an annotated listing of a few call-back functions as
  1228. Xthey are implemented in VLT. Also, it is shown how to initialize the XPR_IO
  1229. Xstructure. Notice that the files supplied in this archive are likely more up to
  1230. Xdate and more extensive than the minimal example given here.
  1231. X
  1232. X/** xprfuncs.c
  1233. X*
  1234. X*   Call-back functions for eXternal PRotocol support
  1235. X*
  1236. X**/
  1237. X#include <functions.h>
  1238. X#include <exec/exec.h>
  1239. X#include <stdio.h>
  1240. X/*
  1241. X*   xproto.h is given in Appendix B
  1242. X*/
  1243. X#include "xproto.h"
  1244. X/*
  1245. X*   xfer.h is a VLT private header file containing some information for
  1246. X*   file transfer protocols
  1247. X*/
  1248. X#include "xfer.h"
  1249. X
  1250. X/*
  1251. X*   These are the C versions of the interface
  1252. X*/
  1253. Xlong        vlt_update(),  vlt_swrite(),  vlt_fread(),  vlt_fopen(),
  1254. X            vlt_fclose(),  vlt_gets(),    vlt_sread(),  vlt_chkabort();
  1255. X/*
  1256. X*   These are the assembly level glue functions, see vltface.asm
  1257. X*/
  1258. Xextern long avlt_update(), avlt_swrite(), avlt_fread(), avlt_fopen(),
  1259. X            avlt_fclose(), avlt_gets(),   avlt_sread(), avlt_chkabort();
  1260. X
  1261. X/**
  1262. X*
  1263. X*   This function initializes an XPR_IO structure.
  1264. X*
  1265. X**/
  1266. Xxpr_setup(IO)
  1267. Xstruct XPR_IO *IO;
  1268. X{
  1269. X/*
  1270. X*   NULL out all the functions we don't do yet.
  1271. X*   Fill the other ones with the addresses to the assembler glue version
  1272. X*   of the interface routines. See vltface.asm
  1273. X*/
  1274. X   IO->xpr_filename  = NULL;
  1275. X   IO->xpr_fopen     = avlt_fopen;
  1276. X   IO->xpr_fclose    = avlt_fclose;
  1277. X   IO->xpr_fread     = avlt_fread;
  1278. X   IO->xpr_fwrite    = NULL;
  1279. X   IO->xpr_sread     = avlt_sread;
  1280. X   IO->xpr_swrite    = avlt_swrite;
  1281. X   IO->xpr_sflush    = NULL;
  1282. X   IO->xpr_update    = avlt_update;
  1283. X   IO->xpr_chkabort  = avlt_chkabort;
  1284. X   IO->xpr_chkmisc   = NULL;
  1285. X   IO->xpr_gets      = avlt_gets;
  1286. X   IO->xpr_setserial = NULL;
  1287. X   IO->xpr_ffirst    = NULL;
  1288. X   IO->xpr_fnext     = NULL;
  1289. X   IO->xpr_finfo     = NULL;
  1290. X   IO->xpr_fseek     = NULL;
  1291. X/*
  1292. X*   Support the 1 defined extension
  1293. X*/
  1294. X   IO->xpr_extension = 1L;
  1295. X/*
  1296. X*   But don't actually implement it yet.
  1297. X*/
  1298. X   IO->xpr_options   = NULL
  1299. X/*
  1300. X*   Especially, NULL out the XPR private data field.
  1301. X*/
  1302. X   IO->xpr_data      = NULL;
  1303. X
  1304. X   return;
  1305. X}
  1306. X
  1307. X/**
  1308. X*
  1309. X*   Interface to VLT's MsgDisplay() function.
  1310. X*
  1311. X**/
  1312. X/*
  1313. X*   These are formats for VLT's requester
  1314. X*/
  1315. Xstatic char *xprnamfmt = "%s\n%s\n\n\n\n";
  1316. Xstatic char *filnamfmt = "\n\n%s\n\n\n";
  1317. Xstatic char *blksizfmt = "\n\n\n\nBlock:  %6ld  --  Block Size:  %6ld\n";
  1318. Xstatic char *errtimfmt = "\n\n\n\n\nErrors: %6ld  --  Timeouts:    %6ld";
  1319. Xstatic char *delayfmt  = "\n\n\n\n\nPacket delay %ld";
  1320. X/*
  1321. X*   Below are some VLT globals to orchestrate the display
  1322. X*/
  1323. Xlong xpr_blocks = 0L, xpr_blocksize = 0L, xpr_errors = 0L, xpr_timeouts = 0L;
  1324. X/*
  1325. X*   The function
  1326. X*/
  1327. Xlong vlt_update(x)
  1328. Xstruct XPR_UPDATE *x;
  1329. X{
  1330. X   extern struct Window *mywindow;
  1331. X   extern char *XPR_Name;
  1332. X/*
  1333. X*   First time, determine the window size (50 chars wide, 5 lines tall).
  1334. X*/
  1335. X   SetMsgWindow(mywindow, 50, 6);
  1336. X/*
  1337. X*   Use VLT's PostMsg function to display all the information.
  1338. X*/
  1339. X   if (x->xpru_updatemask & XPRU_PROTOCOL) {
  1340. X      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_protocol);
  1341. X   }
  1342. X   if (x->xpru_updatemask & XPRU_MSG) {
  1343. X      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_msg);
  1344. X   }
  1345. X   if (x->xpru_updatemask & XPRU_ERRORMSG) {
  1346. X      PostMsg(mywindow, xprnamfmt, XPR_Name, x->xpru_errormsg);
  1347. X   }
  1348. X   if (x->xpru_updatemask & XPRU_FILENAME) {
  1349. X      PostMsg(mywindow, filnamfmt, x->xpru_filename);
  1350. X   }
  1351. X   if (x->xpru_updatemask & XPRU_PACKETDELAY) {
  1352. X      PostMsg(mywindow, delayfmt, x->xpru_packetdelay);
  1353. X   }
  1354. X   if (x->xpru_updatemask & (XPRU_BLOCKS | XPRU_BLOCKSIZE)) {
  1355. X      if (x->xpru_updatemask & XPRU_BLOCKS)    xpr_blocks    = x->xpru_blocks;
  1356. X      if (x->xpru_updatemask & XPRU_BLOCKSIZE) xpr_blocksize = x->xpru_blocksize;
  1357. X      PostMsg(mywindow, blksizfmt, xpr_blocks, xpr_blocksize);
  1358. X   }
  1359. X   if (x->xpru_updatemask & (XPRU_ERRORS | XPRU_TIMEOUTS)) {
  1360. X      if (x->xpru_updatemask & XPRU_ERRORS)   xpr_errors   = x->xpru_errors;
  1361. X      if (x->xpru_updatemask & XPRU_TIMEOUTS) xpr_timeouts = x->xpru_timeouts;
  1362. X      PostMsg(mywindow, errtimfmt, xpr_errors, xpr_timeouts);
  1363. X   }
  1364. X   return(0L);
  1365. X}
  1366. X
  1367. X/**
  1368. X*
  1369. X*   Prompt the user for input
  1370. X*
  1371. X**/
  1372. Xlong vlt_gets(s, t)
  1373. Xchar *s, *t;
  1374. X{
  1375. X/*
  1376. X*   Use VLT's DoRequest() function
  1377. X*/
  1378. X   return((long) DoRequest(mywindow, t, s, NULL, " Cancel "));
  1379. X}
  1380. X
  1381. X/**
  1382. X*
  1383. X*   Write a string to the serial port
  1384. X*
  1385. X**/
  1386. Xlong vlt_swrite(s, n)
  1387. Xchar *s;
  1388. Xlong n;
  1389. X{
  1390. X/*
  1391. X*   Use VLT's SendString() function
  1392. X*/
  1393. X   SendString(s, (int) n);
  1394. X   return(0L);
  1395. X}
  1396. X
  1397. X/**
  1398. X*
  1399. X*   Read characters from the serial port
  1400. X*
  1401. X**/
  1402. Xlong vlt_sread(buff, length, micros)
  1403. Xunsigned char *buff;
  1404. Xlong length, micros;
  1405. X{
  1406. X   extern int timeout;
  1407. X   long secs = 0L;
  1408. X
  1409. X   if (buff == NULL) return(-1L);
  1410. X/*
  1411. X*   Convert timeout to seconds and micros if necessary
  1412. X*/
  1413. X   if (micros) {
  1414. X      if (micros > 1000000L) {
  1415. X         secs   = micros / 1000000L;
  1416. X         micros = micros % 1000000L;
  1417. X      }
  1418. X   }
  1419. X/*
  1420. X*   Cheat! Only return a single character since we have such a nice
  1421. X*   readchar() function in VLT. One day I'll have to modify this to 
  1422. X*   save the odd microsecond...
  1423. X*/
  1424. X   buff[0] = (unsigned char) readchar(secs, micros);
  1425. X/*
  1426. X*   VLT has a global called timeout. This comes in xfer.h.
  1427. X*   If the read was successful, return having read a single character.
  1428. X*/
  1429. X   if (timeout == GOODREAD) return(1L);
  1430. X/*
  1431. X*   Else return error condition
  1432. X*/
  1433. X   return(-1L);
  1434. X}
  1435. X
  1436. X/**
  1437. X*
  1438. X*   Interfaces to stdio
  1439. X*
  1440. X**/
  1441. Xlong vlt_fopen(s, t)
  1442. Xchar *s, *t;
  1443. X{
  1444. X   return((long) fopen(s, t));
  1445. X}
  1446. X
  1447. Xlong vlt_fclose(fp)
  1448. XFILE *fp;
  1449. X{
  1450. X   return((long) fclose(fp));
  1451. X}
  1452. X
  1453. Xlong vlt_fread(buff, size, count, fp)
  1454. Xchar *buff;
  1455. Xlong size, count;
  1456. XFILE *fp;
  1457. X{
  1458. X   int res;
  1459. X   res = fread(buff, (int) size, (int) count, fp);
  1460. X   return((long) res);
  1461. X}
  1462. X
  1463. X/**
  1464. X*
  1465. X*   Check for Abort
  1466. X*
  1467. X**/
  1468. Xlong vlt_chkabort()
  1469. X{
  1470. X/*
  1471. X*   VLT aborts its protocols when the escape key is pressed.
  1472. X*   CheckForKey loops over the UserPort messages looking for an escape.
  1473. X*/
  1474. X   return((long) CheckForKey(69));
  1475. X}
  1476. X                              __                
  1477. X                             /  \ o    /        
  1478. X                       -----/----\----/-----
  1479. X                           /    o \__/          
  1480. X                                                
  1481. X        Clearly, this part of the implementation isn't hard either. The only
  1482. Xthing left is the assembly level glue on the communications program side. You
  1483. Xmay wonder at this point why all this assembly level stuff is necessary. It is
  1484. Xnecessary because many programs and libraries are written in small code/small
  1485. Xdata. This means that both the communications program and the library address
  1486. Xtheir code/data off of some register, in the case of Manx usually A4. The
  1487. Xproblem is that the communications program and the library are loaded in
  1488. Xdifferent parts of memory, while startup code takes care of setting up the
  1489. Xproper value for A4. And the values of A4 are different for the the
  1490. Xcommunications program and the library! Now, if you just call a library
  1491. Xfunction, the assembly level glue does a few things, among which are: (1) saving
  1492. Xthe caller's A4 somewhere safe and (2) retrieving the A4 it stored somewhere
  1493. Xwhen the library was loaded. Then the library function is executed, and the
  1494. Xfunction returns to the glue. The glue then restores A4 to the state it was in
  1495. Xbefore the library call.
  1496. X        In the case of these call-back functions, we have to do the reverse.
  1497. XAfter all, when a function like xpr_update is called, the current value of A4 is
  1498. Xthe one that goes with the library's code. If the call-back function tries to
  1499. Xaccess any data back in the communications program, we're in big trouble.
  1500. X        So what the assembly part of the call-backs has to do is (1) save the
  1501. Xlibrary's A4 (on the stack) and (2) get the value of A4 appropriate for the
  1502. Xcommunications program. Then we can push the various registers onto the stack,
  1503. Xcall the C version of the call-back and then restore the value of A4 to what the
  1504. Xlibrary wants.
  1505. X        For the above call-backs, the assembly level glue is listed below. This
  1506. Xconcludes the documentation on external protocols using Amiga shared libraries.
  1507. XIf you have any questions, comments or suggestions, contact me on BIX.
  1508. X        Meanwhile, have fun!
  1509. X
  1510. X;;; vltface.asm
  1511. X;
  1512. X;   DESCRIPTION:
  1513. X;   ===========
  1514. X;
  1515. X;        This is an interface to VLT callback functions from
  1516. X;        external protocol libraries.
  1517. X;
  1518. X;   AUTHOR/DATE:  W.G.J. Langeveld, March 1989.
  1519. X;   ============
  1520. X;
  1521. X;;;
  1522. X
  1523. X        public  _geta4
  1524. X
  1525. Xsetup   macro
  1526. X        movem.l d2/d3/d4-d7/a2-a6,-(sp)
  1527. X        jsr     _geta4                        ; Get a4.
  1528. X        endm
  1529. X
  1530. Xpush    macro
  1531. X        move.l  \1,-(sp)
  1532. X        endm
  1533. X
  1534. Xfix     macro
  1535. X        ifc     '\1',''
  1536. X                mexit
  1537. X        endc
  1538. X        ifle    \1-8
  1539. X                addq.l  #\1,sp
  1540. X        endc
  1541. X        ifgt    \1-8
  1542. X                lea     \1(sp),sp
  1543. X        endc
  1544. X        endm
  1545. X
  1546. Xrestore macro
  1547. X        fix     \1
  1548. X        movem.l (sp)+,d2/d3/d4-d7/a2-a6        
  1549. X        rts
  1550. X        endm
  1551. X
  1552. X        public  _avlt_fopen
  1553. X        public  _vlt_fopen
  1554. X        public  _avlt_fclose
  1555. X        public  _vlt_fclose
  1556. X        public  _avlt_fread
  1557. X        public  _vlt_fread
  1558. X        public  _avlt_sread
  1559. X        public  _vlt_sread
  1560. X        public  _avlt_swrite
  1561. X        public  _vlt_swrite
  1562. X        public  _avlt_update
  1563. X        public  _vlt_update
  1564. X        public  _avlt_chkabort
  1565. X        public  _vlt_chkabort
  1566. X        public  _avlt_gets
  1567. X        public  _vlt_gets
  1568. X
  1569. X_avlt_fopen:
  1570. X        setup
  1571. X        push    a1
  1572. X        push    a0
  1573. X        jsr     _vlt_fopen
  1574. X        restore 8
  1575. X
  1576. X_avlt_fclose:
  1577. X        setup
  1578. X        push    a0
  1579. X        jsr     _vlt_fclose
  1580. X        restore 4
  1581. X
  1582. X_avlt_fread:
  1583. X        setup
  1584. X        push    a1
  1585. X        push    d1
  1586. X        push    d0
  1587. X        push    a0
  1588. X        jsr     _vlt_fread
  1589. X        restore 16
  1590. X
  1591. X_avlt_sread:
  1592. X        setup
  1593. X        push    d1
  1594. X        push    d0
  1595. X        push    a0
  1596. X        jsr     _vlt_sread
  1597. X        restore 12
  1598. X
  1599. X_avlt_swrite:
  1600. X        setup
  1601. X        push    d0
  1602. X        push    a0
  1603. X        jsr     _vlt_swrite
  1604. X        restore 8
  1605. X
  1606. X_avlt_update:
  1607. X        setup
  1608. X        push    a0
  1609. X        jsr     _vlt_update
  1610. X        restore 4
  1611. X
  1612. X_avlt_chkabort:
  1613. X        setup
  1614. X        jsr     _vlt_chkabort
  1615. X        restore
  1616. X
  1617. X_avlt_gets:
  1618. X        setup
  1619. X        push    a1
  1620. X        push    a0
  1621. X        jsr     _vlt_gets
  1622. X        restore 8
  1623. X
  1624. X                              __                
  1625. X                             /  \ o    /        
  1626. X                       -----/----\----/-----
  1627. X                           /    o \__/          
  1628. X                                                
  1629. X
  1630. X
  1631. X
  1632. X
  1633. X
  1634. X
  1635. X
  1636. XAppendix A: XPR library skeleton.
  1637. X=================================
  1638. X
  1639. X;;; libface.asm
  1640. X;
  1641. X;   DESCRIPTION:
  1642. X;   ===========
  1643. X;
  1644. X;        This is the skeleton for an Amiga Exec library.
  1645. X;        This version is written for Aztec C. It is based on the example
  1646. X;        library by Jim Mackraz who got some stuff from Neil Katin.
  1647. X;        This library implements a protocol transfer library.
  1648. X;        All changes and additions by me.
  1649. X;
  1650. X;   AUTHOR/DATE:  W.G.J. Langeveld, February 1989.
  1651. X;   ============
  1652. X;
  1653. X;;;
  1654. X
  1655. X        include 'exec/types.i'
  1656. X
  1657. Xsetup   macro
  1658. X        movem.l d2/d3/d4-d7/a2-a6,-(sp)
  1659. X        jsr     _geta4                        ;set up a4 for small model
  1660. X        endm
  1661. X
  1662. Xpush    macro
  1663. X        move.l  \1,-(sp)
  1664. X        endm
  1665. X
  1666. Xfix     macro
  1667. X        ifc     '\1',''
  1668. X                mexit
  1669. X        endc
  1670. X        ifle    \1-8
  1671. X                addq.l        #\1,sp
  1672. X        endc
  1673. X        ifgt    \1-8
  1674. X                lea        \1(sp),sp
  1675. X        endc
  1676. X        endm
  1677. X
  1678. Xrestore macro
  1679. X        fix     \1
  1680. X        movem.l (sp)+,d2/d3/d4-d7/a2-a6        
  1681. X        rts
  1682. X        endm
  1683. X
  1684. X        dseg
  1685. X
  1686. X        public  _libfunctab
  1687. X_libfunctab:
  1688. X        dc.l    XPRopen
  1689. X        dc.l    XPRclose
  1690. X        dc.l    XPRexpunge
  1691. X        dc.l    $0000
  1692. X        dc.l    XPRXProtocolCleanup
  1693. X        dc.l    XPRXProtocolSetup
  1694. X        dc.l    XPRXProtocolSend
  1695. X        dc.l    XPRXProtocolReceive
  1696. X        dc.l    $ffffffff
  1697. X
  1698. X        cseg
  1699. X
  1700. X        ;=== library functions
  1701. X        public  _XPROpen
  1702. X        public  _XPRClose
  1703. X        public  _XPRExpunge
  1704. X        public  _XProtocolCleanup
  1705. X        public  _XProtocolSetup
  1706. X        public  _XProtocolSend
  1707. X        public  _XProtocolReceive
  1708. X
  1709. X        public  _geta4
  1710. X
  1711. XXPRopen:
  1712. X        setup
  1713. X        push    a6
  1714. X        jsr     _XPROpen
  1715. X        restore 4
  1716. X
  1717. XXPRclose:
  1718. X        setup
  1719. X        push    a6
  1720. X        jsr     _XPRClose
  1721. X        restore 4
  1722. X
  1723. XXPRexpunge:
  1724. X        setup
  1725. X        push    a6
  1726. X        jsr     _XPRExpunge
  1727. X        restore 4
  1728. X
  1729. XXPRXProtocolCleanup:
  1730. X        setup
  1731. X        push    a0
  1732. X        jsr     _XProtocolCleanup
  1733. X        restore 4
  1734. X
  1735. XXPRXProtocolSetup:
  1736. X        setup
  1737. X        push    a0
  1738. X        jsr     _XProtocolSetup
  1739. X        restore 4
  1740. X
  1741. XXPRXProtocolSend:
  1742. X        setup
  1743. X        push    a0
  1744. X        jsr     _XProtocolSend
  1745. X        restore 4
  1746. X
  1747. XXPRXProtocolReceive:
  1748. X        setup
  1749. X        push    a0
  1750. X        jsr     _XProtocolReceive
  1751. X        restore 4
  1752. X
  1753. X
  1754. X        end
  1755. X
  1756. X
  1757. X
  1758. X
  1759. X
  1760. XAppendix B: The xproto.h include file
  1761. X=====================================
  1762. X
  1763. X/** xproto.h
  1764. X*
  1765. X*   Include file for External Protocol Handling
  1766. X*
  1767. X**/
  1768. X/*
  1769. X*   The structure
  1770. X*/
  1771. Xstruct XPR_IO {
  1772. X                  char  *xpr_filename;      /* File name(s)             */
  1773. X                  long (*xpr_fopen)();      /* Open file                */
  1774. X                  long (*xpr_fclose)();     /* Close file               */
  1775. X                  long (*xpr_fread)();      /* Get char from file       */
  1776. X                  long (*xpr_fwrite)();     /* Put string to file       */
  1777. X                  long (*xpr_sread)();      /* Get char from serial     */
  1778. X                  long (*xpr_swrite)();     /* Put string to serial     */
  1779. X                  long (*xpr_sflush)();     /* Flush serial input buffer*/
  1780. X                  long (*xpr_update)();     /* Print stuff              */
  1781. X                  long (*xpr_chkabort)();   /* Check for abort          */
  1782. X                  long (*xpr_chkmisc)();    /* Check misc. stuff        */
  1783. X                  long (*xpr_gets)();       /* Get string interactively */
  1784. X                  long (*xpr_setserial)();  /* Set and Get serial info  */
  1785. X                  long (*xpr_ffirst)();     /* Find first file name     */
  1786. X                  long (*xpr_fnext)();      /* Find next file name      */
  1787. X                  long (*xpr_finfo)();      /* Return file info         */
  1788. X                  long (*xpr_fseek)();      /* Seek in a file           */
  1789. X                  long  *xpr_extension;     /* Number of extensions     */
  1790. X                  long  *xpr_data;          /* Initialized by Setup.    */
  1791. X                  long (*xpr_options)();    /* Multiple XPR options.    */
  1792. X              };
  1793. X/*
  1794. X*   Number of defined extensions
  1795. X*/
  1796. X#define XPR_EXTENSION 1L
  1797. X
  1798. X/*
  1799. X*   The functions
  1800. X*/
  1801. Xextern long XProtocolSend(),  XProtocolReceive(),
  1802. X            XProtocolSetup(), XProtocolCleanup();
  1803. X/*
  1804. X*   The update structure
  1805. X*/
  1806. Xstruct XPR_UPDATE {     long  xpru_updatemask;
  1807. X                        char *xpru_protocol;
  1808. X                        char *xpru_filename;
  1809. X                        long  xpru_filesize;
  1810. X                        char *xpru_msg;
  1811. X                        char *xpru_errormsg;
  1812. X                        long  xpru_blocks;
  1813. X                        long  xpru_blocksize;
  1814. X                        long  xpru_bytes;
  1815. X                        long  xpru_errors;
  1816. X                        long  xpru_timeouts;
  1817. X                        long  xpru_packettype;
  1818. X                        long  xpru_packetdelay;
  1819. X                        long  xpru_chardelay;
  1820. X                        char *xpru_blockcheck;
  1821. X                        char *xpru_expecttime;
  1822. X                        char *xpru_elapsedtime;
  1823. X                        long  xpru_datarate;
  1824. X                        long  xpru_reserved1;
  1825. X                        long  xpru_reserved2;
  1826. X                        long  xpru_reserved3;
  1827. X                        long  xpru_reserved4;
  1828. X                        long  xpru_reserved5;
  1829. X                   };
  1830. X/*
  1831. X*   The possible bit values for the xpru_updatemask are:
  1832. X*/
  1833. X#define XPRU_PROTOCOL           0x00000001L
  1834. X#define XPRU_FILENAME           0x00000002L
  1835. X#define XPRU_FILESIZE           0x00000004L
  1836. X#define XPRU_MSG                0x00000008L
  1837. X#define XPRU_ERRORMSG           0x00000010L
  1838. X#define XPRU_BLOCKS             0x00000020L
  1839. X#define XPRU_BLOCKSIZE          0x00000040L
  1840. X#define XPRU_BYTES              0x00000080L
  1841. X#define XPRU_ERRORS             0x00000100L
  1842. X#define XPRU_TIMEOUTS           0x00000200L
  1843. X#define XPRU_PACKETTYPE         0x00000400L
  1844. X#define XPRU_PACKETDELAY        0x00000800L
  1845. X#define XPRU_CHARDELAY          0x00001000L
  1846. X#define XPRU_BLOCKCHECK         0x00002000L
  1847. X#define XPRU_EXPECTTIME         0x00004000L
  1848. X#define XPRU_ELAPSEDTIME        0x00008000L
  1849. X#define XPRU_DATARATE           0x00010000L
  1850. X/*
  1851. X*   The xpro_option structure
  1852. X*/
  1853. Xstruct xpr_option {
  1854. X   char *xpro_description;      /* description of the option                  */
  1855. X   long  xpro_type;             /* type of option                             */
  1856. X   char *xpro_value;            /* pointer to a buffer with the current value */
  1857. X   long  xpro_length;           /* buffer size                                */
  1858. X}
  1859. X/*
  1860. X*   Valid values for xpro_type are:
  1861. X*/
  1862. X#define XPRO_BOOLEAN 1L         /* xpro_value is "yes", "no", "on" or "off"   */
  1863. X#define XPRO_LONG    2L         /* xpro_value is string representing a number */
  1864. X#define XPRO_STRING  3L         /* xpro_value is a string                     */
  1865. X
  1866. SHAR_EOF
  1867. echo "End of archive 2 (of 2)"
  1868. # if you want to concatenate archives, remove anything after this line
  1869. exit
  1870.